package com.atguigu.guli.service.trade.service.impl;

import com.atguigu.guli.common.util.HttpClientUtils;
import com.atguigu.guli.common.util.StreamUtils;
import com.atguigu.guli.service.base.exception.GuliException;
import com.atguigu.guli.service.base.result.ResultCodeEnum;
import com.atguigu.guli.service.trade.entity.Order;
import com.atguigu.guli.service.trade.entity.PayLog;
import com.atguigu.guli.service.trade.service.EduFeignClient;
import com.atguigu.guli.service.trade.service.OrderService;
import com.atguigu.guli.service.trade.service.PayLogService;
import com.atguigu.guli.service.trade.service.WxPayService;
import com.atguigu.guli.service.trade.util.WxPayProperties;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.github.wxpay.sdk.WXPayUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;


import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Service
@Slf4j
public class WxPayServiceImpl implements WxPayService {

    @Autowired
    OrderService orderService;

    @Autowired
    PayLogService payLogService;

    @Autowired
    WxPayProperties wxPayProperties;
    @Override
    public Map createNative(String orderNo, HttpServletRequest request) {
        Order order = orderService.getOrderByOrderNo(orderNo);
        String url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
        try {
            HashMap<String, String> map = new HashMap<>();
            map.put("appid",wxPayProperties.getAppId());//wx平台分配的应用的id
            map.put("mch_id",wxPayProperties.getPartner());//使用wx平台为商户分配的编号
            map.put("nonce_str", WXPayUtil.generateNonceStr());//随机字符串
//        map.put("sign",""); // 保证数据安全不会被篡改
            map.put("body",order.getCourseTitle());//展示给wx用户的商品 信息
            map.put("out_trade_no",order.getOrderNo());//订单编号
            map.put("total_fee",order.getTotalFee()+"");

            map.put("spbill_create_ip",request.getRemoteHost());//客户端ip地址
            map.put("notify_url",wxPayProperties.getNotifyUrl());//用户扫描本次生成的二维码支付成功后的回调
            map.put("trade_type","NATIVE");//本次是web项目的支付

            String signatureXmlStr = WXPayUtil.generateSignedXml(map,wxPayProperties.getPartnerKey());

            HttpClientUtils client = new HttpClientUtils(url);
            client.setXmlParam(signatureXmlStr);
            client.post();
            String content = client.getContent();
            boolean signatureValid = WXPayUtil.isSignatureValid(content, wxPayProperties.getPartnerKey());
            if(!signatureValid){
                //签名或数据被篡改
                throw new GuliException(ResultCodeEnum.PAY_UNIFIEDORDER_ERROR);
            }
            Map<String, String> resultMap = WXPayUtil.xmlToMap(content);
            System.out.println(resultMap);
            //错误处理
            if("FAIL".equals(resultMap.get("return_code")) || "FAIL".equals(resultMap.get("result_code"))){
                log.error("微信支付统一下单错误 - "
                        + "return_code: " + resultMap.get("return_code")
                        + "return_msg: " + resultMap.get("return_msg")
                        + "result_code: " + resultMap.get("result_code")
                        + "err_code: " + resultMap.get("err_code")
                        + "err_code_des: " + resultMap.get("err_code_des"));

                throw new GuliException(ResultCodeEnum.PAY_UNIFIEDORDER_ERROR);
            }

            //组装需要的内容
            Map<String, Object> lastmap = new HashMap<>();
            lastmap.put("result_code", resultMap.get("result_code"));//响应码
            lastmap.put("code_url", resultMap.get("code_url"));//生成二维码的url
            lastmap.put("course_id", order.getCourseId());//课程id
            lastmap.put("total_fee", order.getTotalFee()+"");//订单总金额
            lastmap.put("out_trade_no", orderNo);//订单号
            lastmap.put("orderId",order.getId());
            return lastmap;


        } catch (Exception e) {
            throw new GuliException(ResultCodeEnum.PAY_UNIFIEDORDER_ERROR);
        }
    }

    @Autowired
    EduFeignClient eduFeignClient;
    @Transactional
    @Override
    public String nofityurl(HttpServletRequest request) {
        Map returnMap = new HashMap();//用来存放给微信的响应数据
        returnMap.put("return_code","FAIL");
        returnMap.put("return_msg","FAIL");
        try {
            String callbackStr = StreamUtils.inputStream2String(request.getInputStream(), "UTF-8");
            boolean signatureValid = WXPayUtil.isSignatureValid(callbackStr, wxPayProperties.getPartnerKey());
            if(!signatureValid){
                returnMap.put("return_msg","签名错误");
                return WXPayUtil.mapToXml(returnMap);
            }
            Map<String, String> map = WXPayUtil.xmlToMap(callbackStr);
            System.out.println(map);
            String total_fee = map.get("total_fee");
            String out_trade_no = map.get("out_trade_no");
            LambdaQueryWrapper<Order> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Order::getOrderNo , out_trade_no);
            Order order = orderService.getOne(queryWrapper);
            if(order.getTotalFee()!=Long.parseLong(total_fee)|| order==null){
                returnMap.put("return_msg","用户支付金额和订单金额不一致");
                return WXPayUtil.mapToXml(returnMap);
            }
            if(order.getStatus()==0){//订单状态未更新
                LambdaUpdateWrapper<Order> updateWrapper = new LambdaUpdateWrapper<>();
                updateWrapper.set(Order::getStatus , 1);//支付状态 1代表已支付
                updateWrapper.set(Order::getPayType , 1);//支付类型
                orderService.update(updateWrapper);
                //保存订单支付日志
                PayLog payLog = new PayLog();
                payLog.setPayType(1);
                payLog.setPayTime(new Date());
                payLog.setTotalFee(order.getTotalFee());
                payLog.setOrderNo(order.getOrderNo());
                payLog.setTradeState("1");
                payLog.setTransactionId(map.get("transaction_id"));
                payLog.setAttr(callbackStr);
                payLogService.save(payLog);
                //更新课程销量：远程访问service-edu更新课程表课程的销量
                eduFeignClient.updateSales(order.getCourseId());

            }
            returnMap.put("return_code","SUCCESS");
            returnMap.put("return_msg","OK");
            return WXPayUtil.mapToXml(returnMap);
        } catch (Exception e) {
            returnMap.put("return_msg","出现异常");
            try {
                return WXPayUtil.mapToXml(returnMap);
            } catch (Exception e1) {
                throw new GuliException(ResultCodeEnum.ILLEGAL_CALLBACK_REQUEST_ERROR,e);
            }
        }

    }
}
